home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-13
/
thesrc10.zip
/
THE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-12
|
20KB
|
533 lines
/***********************************************************************/
/* THE.C - The Hessling Editor */
/***********************************************************************/
/*
* THE - The Hessling Editor. A text editor similar to VM/CMS xedit.
* Copyright (C) 1991,1992 Mark Hessling
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
*
* The Free Software Foundation, Inc.
* 675 Mass Ave,
* Cambridge, MA 02139 USA.
*
*
* If you make modifications to this software that you feel increases
* it usefulness for the rest of the community, please email the
* changes, enhancements, bug fixes as well as any and all ideas to me.
* This software is going to be maintained and enhanced as deemed
* necessary by the community.
*
* Mark Hessling email: M.Hessling@itc.gu.edu.au
* 36 David Road Phone: +61 7 849 7731
* Holland Park Fax: +61 7 875 7877
* QLD 4121
* Australia
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#define MAIN 1
#include "the.h"
/*#define DEBUG 1*/
/*--------------------------- global data -----------------------------*/
WINDOW *foot,*error_window,*divider;
VIEW_DETAILS *vd_current=(VIEW_DETAILS *)NULL;
VIEW_DETAILS *vd_first=(VIEW_DETAILS *)NULL;
VIEW_DETAILS *vd_mark=(VIEW_DETAILS *)NULL;
char number_of_views = 0; /* number of views */
char number_of_files = 0; /* number of files */
char display_screens = 1; /* number of screens */
char current_screen = 0;
SCREEN_DETAILS screen[MAX_SCREENS]; /* 2 screen structures */
bool horizontal=TRUE;
short save_coord_x[VIEW_WINDOWS];
short save_coord_y[VIEW_WINDOWS];
LINE *next_line,*curr_line;
LINE *first_profile_command=NULL,*current_profile_command=NULL;
LINE *first_file_name=NULL,*current_file_name=NULL;
char error_on_screen;
unsigned char *rec;
unsigned short rec_len = 0; /* length of rec */
unsigned char *cmd_rec;
unsigned short cmd_rec_len = 0; /* length of cmd_rec */
unsigned char focus_changed = NO; /* indicates if focus line has changed */
unsigned char current_changed = NO; /* indicates if current line has changed */
unsigned char mode_insert=YES; /* defines insert mode toggle */
unsigned char in_profile; /* indicates if processing profile */
unsigned char file_read=NO; /* indicates if we have read the file */
unsigned char *profilename = (unsigned char *)"PROFILE.THE";
unsigned char *helpfilename = (unsigned char *)"THE.HLP";
unsigned char *tempfilename = (unsigned char *)"THE.$$$";
#ifdef VMS
unsigned char *dirfilename = (unsigned char *)"DIR.THE";
#else
unsigned char *dirfilename = (unsigned char *)"DIR.DIR";
#endif
unsigned char help_pathname[MAX_FILE_NAME+1];
unsigned char profile_pathname[MAX_FILE_NAME+1];
unsigned char dir_pathname[MAX_FILE_NAME+1];
unsigned char dir_filename[MAX_FILE_NAME+1];
unsigned char curr_path[MAX_FILE_NAME+1];
unsigned char sp_path[MAX_FILE_NAME+1];
unsigned char sp_fname[MAX_FILE_NAME+1];
unsigned char dir_path[MAX_FILE_NAME+1]; /* for dir and ls commands */
unsigned short file_start = 36;
unsigned char *last_target;
#ifdef UNIX
unsigned char *spooler_name;
#endif
char file_disposition;
struct stat stat_buf;
/*---------------------------------------------------------------------*/
/* Following are for getopt function(s). */
/*---------------------------------------------------------------------*/
extern char *optarg;
extern int optind;
/*---------------------- function definitions -------------------------*/
void handle_signal();
void init_signals();
void set_default_colours();
void display_info();
int Edit();
/***********************************************************************/
#ifdef PROTO
int main(int argc, unsigned char *argv[])
#else
int main(argc,argv)
int argc;
unsigned char *argv[];
#endif
/***********************************************************************/
{
/*-------------------------- external data ----------------------------*/
/*---------------------- function definitions -------------------------*/
/*--------------------------- local data ------------------------------*/
register int i,j,k;
unsigned char *prf;
char c;
int malloc_fd;
bool trap_signals=TRUE;
/*--------------------------- processing ------------------------------*/
#ifdef TRACE
trace_initialise();
trace_function("the.c: main");
#endif
/*---------------------------------------------------------------------*/
/* Set up flag to indicate that we are not interactive...yet. */
/*---------------------------------------------------------------------*/
in_profile = YES;
/*---------------------------------------------------------------------*/
/* Call insertmode command to set default mode to overwrite. Main */
/* reason for this is for the DOS version to set the shape of the */
/* cursor. */
/*---------------------------------------------------------------------*/
Insertmode((unsigned char *)"");
/*---------------------------------------------------------------------*/
/* Initialise the printer spooler. */
/*---------------------------------------------------------------------*/
#ifdef UNIX
if ((spooler_name = (unsigned char *)memMalloc(4,"spooler")) == NULL)
{
display_error(30,"");
exit_clean(1);
}
strcpy(spooler_name,"lpr");
#endif
/*---------------------------------------------------------------------*/
/* Set up memory for profile file name. */
/*---------------------------------------------------------------------*/
if ((prf = (unsigned char *)memMalloc(80,"prf *")) == NULL)
{
display_error(30,"");
exit_clean(1);
}
strcpy(prf,"");
while ((c = getopt(argc,argv,"sp:w:h?")) != (-1))
switch(c)
{
case 's': /* don't trap signals */
trap_signals = FALSE;
break;
case 'p': /* profile file name */
strcpy(prf,optarg);
break;
case 'w': /* width of line */
MAX_LINE_LENGTH = (short)atoi(optarg);
if (MAX_LINE_LENGTH < 10)
{
display_error(5,"width MUST be >= 10");
exit_clean(1);
}
break;
case 'h':
case '?':
display_info();
exit_clean(0);
break;
default:
break;
}
if (optind<argc)
{
while(optind<argc)
{
if ((current_file_name = add_line(first_file_name,
current_file_name,
argv[optind],
strlen(argv[optind]))) == NULL)
{
display_error(30,"");
exit_clean(1);
}
if (first_file_name == NULL)
first_file_name = current_file_name;
optind++;
}
}
else
{
if ((current_file_name = add_line(first_file_name,
current_file_name,
CURRENT_DIR,
strlen(CURRENT_DIR))) == NULL)
{
display_error(30,"");
exit_clean(1);
}
if (first_file_name == NULL)
first_file_name = current_file_name;
}
mark_end_col=MAX_LINE_LENGTH-1;
/*---------------------------------------------------------------------*/
/* Allocate some memory to last_target and set it to a blank value. */
/*---------------------------------------------------------------------*/
if ((last_target = (unsigned char *)memMalloc(80,"last target")) == NULL)
exit_clean(1);
strcpy(last_target,"");
/*---------------------------------------------------------------------*/
/* Allocate some memory to rec. */
/*---------------------------------------------------------------------*/
if ((rec = (unsigned char *)memMalloc(MAX_LINE_LENGTH,"rec")) == NULL)
exit_clean(1);
/*---------------------------------------------------------------------*/
/* Determine the current working directory. */
/* Do this before any other file setting up so that we don't change the*/
/* current directory from the default. */
/*---------------------------------------------------------------------*/
#ifdef MALLOC_DEBUG
malloc_fd = open("malloc.dump",O_RDWR);
malloc_dump(malloc_fd);
malloc_chain_check(1);
close(malloc_fd);
fprintf(stderr,"Just before getcwd()\n");
#endif
getcwd(curr_path,MAX_FILE_NAME);
/*---------------------------------------------------------------------*/
/* Determine calling path for help and profile files. */
/*---------------------------------------------------------------------*/
strcpy(profile_pathname,argv[0]);
i = strzreveq(profile_pathname,SLASH);
if (i != (-1))
profile_pathname[i+1] = '\0';
strcpy(help_pathname,profile_pathname);
strcat(help_pathname,helpfilename);
strcat(profile_pathname,profilename);
/*---------------------------------------------------------------------*/
/* Set up filename for directory temporary file (DIR.DIR) */
/*---------------------------------------------------------------------*/
#ifdef UNIX
strcpy(dir_pathname,getenv("HOME"));
#endif
#if defined(DOS) || defined(OS2)
strcpy(dir_pathname,"\\");
#endif
#ifdef VMS
strcpy(dir_pathname,"");
#endif
if (strlen(dir_pathname) > 0)
if (*(dir_pathname+strlen(dir_pathname)-1) != SLASH)
strcat(dir_pathname,STR_SLASH);
strcat(dir_pathname,dirfilename);
if (splitpath(dir_pathname) == ERROR)
exit_clean(1);
strcpy(dir_pathname,sp_path);
strcpy(dir_filename,sp_fname);
/*---------------------------------------------------------------------*/
/* Set up default values for SET commands etc. */
/*---------------------------------------------------------------------*/
set_defaults();
set_screen_defaults();
/*---------------------------------------------------------------------*/
/* Set up initial colours to 0. */
/*---------------------------------------------------------------------*/
for (i=0;i<ATTR_MAX;i++)
colour[i] = (chtype)0;
/*---------------------------------------------------------------------*/
/* Initialise command array to empty strings. */
/*---------------------------------------------------------------------*/
init_command();
/*---------------------------------------------------------------------*/
/* Read the profile file and execute any 'set' commands that must be */
/* executed BEFORE we read the file to edit. If the commands in the */
/* profile file are to be executed against the file to edit, save the */
/* commands in a linked list to be executed after we read the file. */
/*---------------------------------------------------------------------*/
if (get_profile(prf) == QUIT)
exit_clean(0);
if (get_file(first_file_name->line) == ERROR)
exit_clean(1);
CURRENT_VIEW->current_window = WINDOW_COMMAND;
file_read = YES;
/* process any post file commands */
/*---------------------------------------------------------------------*/
/* Set rec to point to the first line ie. Top of File */
/*---------------------------------------------------------------------*/
memset(rec,' ',MAX_LINE_LENGTH);
rec_len = strlen(TOP_OF_FILE);
memcpy(rec,TOP_OF_FILE,rec_len);
current_profile_command = first_profile_command;
while(current_profile_command != NULL)
{
if (command_line(current_profile_command->line) != OK)
exit_clean(1);
current_profile_command = current_profile_command->next;
}
ll_free(first_profile_command);
/*---------------------------------------------------------------------*/
/* Start up curses. This allows profile commands to be processed before*/
/* curses starts. */
/*---------------------------------------------------------------------*/
if (trap_signals)
init_signals();
initscr();
#ifdef COLOR_CURSES
if (has_colors() == TRUE)
start_color();
#endif
#ifndef VMS
cbreak();
#endif
#ifndef MINIX
raw();
#endif
#if defined(DOS) || defined(OS2)
raw_output(TRUE);
#endif
nonl();
noecho();
#if !defined(SUN) && !defined(VMS)
keypad(stdscr,TRUE);
#endif
in_profile = NO;
/*---------------------------------------------------------------------*/
/* Allocate memory to cmd_rec and set it to blanks. */
/* This is done here so that COLS is valid; set up by initscr(). */
/*---------------------------------------------------------------------*/
if ((cmd_rec = (unsigned char *)memMalloc(COLS,"cmd_rec")) == NULL)
exit_clean(1);
memset(cmd_rec,' ',COLS);
cmd_rec_len = 0;
/*---------------------------------------------------------------------*/
/* Set up default colours for each window component. */
/*---------------------------------------------------------------------*/
set_screen_defaults();
set_default_colours();
/*---------------------------------------------------------------------*/
/* Set up all windows for the first file. */
/* This also sets up 'colours' for monochrome terminals and screens. */
/*---------------------------------------------------------------------*/
set_up_windows();
foot = newwin(1,COLS,LINES-1,0);
error_window = newwin(1,COLS,LINES-1,0);
divider = newwin(LINES-1,2,0,(COLS/2)-1);
wattrset(foot,colour[ATTR_STATAREA]);
wattrset(error_window,colour[ATTR_MSGLINE]);
wattrset(divider,colour[ATTR_DIVIDER]);
for (i=0;i<COLS;i++)
mvwaddch(foot,0,i,' ');
wmove(foot,0,0);
waddstr(foot,"THE 1.0");
wmove(divider,0,0);
for (i=0;i<LINES-1;i++)
mvwaddstr(divider,i,0,"||");
/*---------------------------------------------------------------------*/
/* Edit any other files input on the command line. */
/*---------------------------------------------------------------------*/
current_file_name = first_file_name->next;
while(current_file_name != NULL)
{
if (Edit(current_file_name->line) == ERROR)
exit_clean(1);
current_file_name = current_file_name->next;
}
ll_free(first_file_name);
CURRENT_VIEW = CURRENT_SCREEN.screen_view = vd_first;
pre_process_line(CURRENT_VIEW->focus_line);
/*---------------------------------------------------------------------*/
/* This is where it all happens. */
/*---------------------------------------------------------------------*/
editor();
strcpy(sp_path,dir_pathname);
strcat(sp_path,dir_filename);
remove_file(sp_path);
/*---------------------------------------------------------------------*/
/* Free up the dynamically allocated memory. */
/*---------------------------------------------------------------------*/
free_define_memory();
memFree(last_target,"last target");
memFree(rec,"rec");
memFree(cmd_rec,"cmd_rec");
memFree(prf,"prf");
add_to_recovery_list(NULL,(-1)); /* frees up memory for recovery */
wmove(foot,0,4);
waddstr(foot,"- END");
wrefresh(foot);
#ifdef UNIX
memFree(spooler_name,"spooler");
#endif
delwin(divider);
delwin(error_window);
delwin(foot);
endwin();
exit_clean(0);
}
/***********************************************************************/
#ifdef PROTO
void init_signals(void)
#else
void init_signals()
#endif
/***********************************************************************/
{
/*--------------------------- local data ------------------------------*/
/*--------------------------- processing ------------------------------*/
#ifdef TRACE
trace_function("the.c: init_signals");
#endif
#ifdef UNIX
signal(SIGQUIT,handle_signal);
signal(SIGHUP,handle_signal);
signal(SIGBUS,handle_signal);
signal(SIGABRT,handle_signal);
signal(SIGFPE,handle_signal);
signal(SIGSEGV,handle_signal);
signal(SIGINT,handle_signal);
signal(SIGTERM,handle_signal);
#endif
#ifdef TRACE
trace_return();
#endif
return;
}
#ifdef UNIX
/***********************************************************************/
#ifdef PROTO
void handle_signal(int errno)
#else
void handle_signal(errno)
int errno;
#endif
/***********************************************************************/
{
/*--------------------------- local data ------------------------------*/
/*--------------------------- processing ------------------------------*/
#ifdef TRACE
trace_function("the.c: handle_signal");
#endif
endwin();
fprintf(stderr,"\nTHE terminated with signal: %d\n\n",errno);
exit_clean(2);
}
#endif
/***********************************************************************/
#ifdef PROTO
void display_info(void)
#else
void display_info()
#endif
/***********************************************************************/
{
/*--------------------------- local data ------------------------------*/
/*--------------------------- processing ------------------------------*/
fprintf(stderr,"\nTHE 1.0 Copyright (C) 1991,1992 Mark Hessling\n");
fprintf(stderr,"All rights reserved.\n");
fprintf(stderr,"THE is distributed under the terms of the GNU\n");
fprintf(stderr,"General Public License and comes with NO WARRANTY.\n");
fprintf(stderr,"See the file COPYING for details.\n");
fprintf(stderr,"\nUsage: THE [-s] [-p profile] [-w width] [filename [...] | dir [...]]\n\n");
fflush(stderr);
return;
}
/***********************************************************************/
#ifdef PROTO
void exit_clean(short err_num)
#else
void exit_clean(err_num)
short err_num;
#endif
/***********************************************************************/
{
/*--------------------------- local data ------------------------------*/
#ifdef DOS
char get_mode(void);
#endif
/*--------------------------- processing ------------------------------*/
#ifdef TRACE
trace_function("the.c: exit_clean");
#endif
#if defined(DOS) || defined(OS2)
mode_insert=NO;
draw_cursor();
#endif
if (file_exists(tempfilename))
remove_file(tempfilename);
#ifdef TRACE
trace_return();
#endif
exit(err_num);
}